using StackExchange.Redis;
using System.Text.Json;

namespace BasicData.API.Services
{
    /// <summary>
    /// Redis帮助类
    /// </summary>
    public class RedisHelper
    {
        private readonly ConnectionMultiplexer _redis;
        private readonly IDatabase _db;
        private readonly IConfiguration _configuration;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration">配置</param>
        public RedisHelper(IConfiguration configuration)
        {
            _configuration = configuration;
            
            // 从配置中读取Redis连接信息
            string host = _configuration["Redis:Host"];
            int port = int.Parse(_configuration["Redis:Port"]);
            string password = _configuration["Redis:Password"];
            int database = int.Parse(_configuration["Redis:Database"]);
            int connectTimeout = int.Parse(_configuration["Redis:ConnectTimeout"]);
            
            // 创建连接配置
            var configOptions = new ConfigurationOptions
            {
                EndPoints = { { host, port } },
                Password = password,
                DefaultDatabase = database,
                ConnectTimeout = connectTimeout,
                AbortOnConnectFail = false
            };
            
            // 创建连接
            _redis = ConnectionMultiplexer.Connect(configOptions);
            _db = _redis.GetDatabase();
        }

        /// <summary>
        /// 设置字符串值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>是否成功</returns>
        public bool StringSet(string key, string value, TimeSpan? expiry = null)
        {
            return _db.StringSet(key, value, expiry);
        }

        /// <summary>
        /// 获取字符串值
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public string StringGet(string key)
        {
            return _db.StringGet(key);
        }

        /// <summary>
        /// 设置对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>是否成功</returns>
        public bool Set<T>(string key, T value, TimeSpan? expiry = null)
        {
            string json = JsonSerializer.Serialize(value);
            return StringSet(key, json, expiry);
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">键</param>
        /// <returns>对象</returns>
        public T Get<T>(string key)
        {
            string value = StringGet(key);
            if (string.IsNullOrEmpty(value))
                return default;
            
            return JsonSerializer.Deserialize<T>(value);
        }

        /// <summary>
        /// 删除键
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>是否成功</returns>
        public bool Delete(string key)
        {
            return _db.KeyDelete(key);
        }

        /// <summary>
        /// 判断键是否存在
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>是否存在</returns>
        public bool Exists(string key)
        {
            return _db.KeyExists(key);
        }

        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="expiry">过期时间</param>
        /// <returns>是否成功</returns>
        public bool SetExpiry(string key, TimeSpan expiry)
        {
            return _db.KeyExpire(key, expiry);
        }

        /// <summary>
        /// 哈希表设置
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="hashField">哈希字段</param>
        /// <param name="value">值</param>
        /// <returns>是否成功</returns>
        public bool HashSet(string key, string hashField, string value)
        {
            return _db.HashSet(key, hashField, value);
        }

        /// <summary>
        /// 哈希表获取
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="hashField">哈希字段</param>
        /// <returns>值</returns>
        public string HashGet(string key, string hashField)
        {
            return _db.HashGet(key, hashField);
        }

        /// <summary>
        /// 哈希表删除
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="hashField">哈希字段</param>
        /// <returns>是否成功</returns>
        public bool HashDelete(string key, string hashField)
        {
            return _db.HashDelete(key, hashField);
        }

        /// <summary>
        /// 列表左侧插入
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns>列表长度</returns>
        public long ListLeftPush(string key, string value)
        {
            return _db.ListLeftPush(key, value);
        }

        /// <summary>
        /// 列表右侧插入
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns>列表长度</returns>
        public long ListRightPush(string key, string value)
        {
            return _db.ListRightPush(key, value);
        }

        /// <summary>
        /// 列表左侧弹出
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public string ListLeftPop(string key)
        {
            return _db.ListLeftPop(key);
        }

        /// <summary>
        /// 列表右侧弹出
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public string ListRightPop(string key)
        {
            return _db.ListRightPop(key);
        }

        /// <summary>
        /// 获取列表长度
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>列表长度</returns>
        public long ListLength(string key)
        {
            return _db.ListLength(key);
        }

        /// <summary>
        /// 获取列表范围
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="start">开始索引</param>
        /// <param name="stop">结束索引</param>
        /// <returns>列表值</returns>
        public string[] ListRange(string key, long start, long stop)
        {
            var values = _db.ListRange(key, start, stop);
            return values.Select(x => (string)x).ToArray();
        }

        /// <summary>
        /// 发布消息
        /// </summary>
        /// <param name="channel">频道</param>
        /// <param name="message">消息</param>
        /// <returns>接收到消息的客户端数量</returns>
        public long Publish(string channel, string message)
        {
            var sub = _redis.GetSubscriber();
            return sub.Publish(channel, message);
        }

        /// <summary>
        /// 订阅消息
        /// </summary>
        /// <param name="channel">频道</param>
        /// <param name="handler">处理程序</param>
        public void Subscribe(string channel, Action<string> handler)
        {
            var sub = _redis.GetSubscriber();
            sub.Subscribe(channel, (_, message) => handler(message));
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="channel">频道</param>
        public void Unsubscribe(string channel)
        {
            var sub = _redis.GetSubscriber();
            sub.Unsubscribe(channel);
        }

        /// <summary>
        /// 获取所有键
        /// </summary>
        /// <param name="pattern">模式</param>
        /// <returns>键集合</returns>
        public IEnumerable<string> GetAllKeys(string pattern = "*")
        {
            var server = _redis.GetServer(_redis.GetEndPoints().First());
            return server.Keys(pattern: pattern).Select(key => (string)key);
        }

        /// <summary>
        /// 清空数据库
        /// </summary>
        public void FlushDatabase()
        {
            var server = _redis.GetServer(_redis.GetEndPoints().First());
            server.FlushDatabase();
        }
    }
} 